package com.lvfuyang.commonproject.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

/**
 * SM4国密加密解密工具类
 */
public class SM4Util {
    
    static {
        // 添加BouncyCastle提供者
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }
    
    private static final String ALGORITHM = "SM4";
    private static final String TRANSFORMATION = "SM4/ECB/PKCS7Padding";
    private static final String PROVIDER = "BC";
    
    /**
     * 生成SM4密钥（128位）
     */
    public static String generateKey() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM, PROVIDER);
            keyGen.init(128, new SecureRandom());
            SecretKey secretKey = keyGen.generateKey();
            return Base64.getEncoder().encodeToString(secretKey.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException("生成SM4密钥失败", e);
        }
    }
    
    /**
     * 生成随机SM4密钥（简化版本）
     */
    public static String generateRandomKey() {
        byte[] keyBytes = new byte[16]; // 128位 = 16字节
        new SecureRandom().nextBytes(keyBytes);
        return Base64.getEncoder().encodeToString(keyBytes);
    }
    
    /**
     * SM4加密
     * @param plaintext 明文
     * @param key Base64编码的密钥
     * @return Base64编码的密文
     */
    public static String encrypt(String plaintext, String key) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(key);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            
            Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            
            byte[] encrypted = cipher.doFinal(plaintext.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("SM4加密失败", e);
        }
    }
    
    /**
     * SM4解密
     * @param ciphertext Base64编码的密文
     * @param key Base64编码的密钥
     * @return 明文
     */
    public static String decrypt(String ciphertext, String key) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(key);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            
            Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
            return new String(decrypted, "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("SM4解密失败", e);
        }
    }
    
    /**
     * 使用Hex格式的密钥进行加密
     */
    public static String encryptHex(String plaintext, String hexKey) {
        try {
            byte[] keyBytes = Hex.decode(hexKey);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            
            Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            
            byte[] encrypted = cipher.doFinal(plaintext.getBytes("UTF-8"));
            return Hex.toHexString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("SM4加密失败", e);
        }
    }
    
    /**
     * 使用Hex格式的密钥进行解密
     */
    public static String decryptHex(String hexCiphertext, String hexKey) {
        try {
            byte[] keyBytes = Hex.decode(hexKey);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            
            Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            
            byte[] decrypted = cipher.doFinal(Hex.decode(hexCiphertext));
            return new String(decrypted, "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("SM4解密失败", e);
        }
    }
} 